home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / python2.5 / tarfile.py < prev    next >
Encoding:
Python Source  |  2007-05-02  |  72.4 KB  |  2,177 lines

  1. #! /usr/bin/python2.5
  2. # -*- coding: iso-8859-1 -*-
  3. #-------------------------------------------------------------------
  4. # tarfile.py
  5. #-------------------------------------------------------------------
  6. # Copyright (C) 2002 Lars GustΣbel <lars@gustaebel.de>
  7. # All rights reserved.
  8. #
  9. # Permission  is  hereby granted,  free  of charge,  to  any person
  10. # obtaining a  copy of  this software  and associated documentation
  11. # files  (the  "Software"),  to   deal  in  the  Software   without
  12. # restriction,  including  without limitation  the  rights to  use,
  13. # copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. # copies  of  the  Software,  and to  permit  persons  to  whom the
  15. # Software  is  furnished  to  do  so,  subject  to  the  following
  16. # conditions:
  17. #
  18. # The above copyright  notice and this  permission notice shall  be
  19. # included in all copies or substantial portions of the Software.
  20. #
  21. # THE SOFTWARE IS PROVIDED "AS  IS", WITHOUT WARRANTY OF ANY  KIND,
  22. # EXPRESS OR IMPLIED, INCLUDING  BUT NOT LIMITED TO  THE WARRANTIES
  23. # OF  MERCHANTABILITY,  FITNESS   FOR  A  PARTICULAR   PURPOSE  AND
  24. # NONINFRINGEMENT.  IN  NO  EVENT SHALL  THE  AUTHORS  OR COPYRIGHT
  25. # HOLDERS  BE LIABLE  FOR ANY  CLAIM, DAMAGES  OR OTHER  LIABILITY,
  26. # WHETHER  IN AN  ACTION OF  CONTRACT, TORT  OR OTHERWISE,  ARISING
  27. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  28. # OTHER DEALINGS IN THE SOFTWARE.
  29. #
  30. """Read from and write to tar format archives.
  31. """
  32.  
  33. __version__ = "$Revision: 53162 $"
  34. # $Source$
  35.  
  36. version     = "0.8.0"
  37. __author__  = "Lars GustΣbel (lars@gustaebel.de)"
  38. __date__    = "$Date: 2006-12-27 21:36:58 +1100 (Wed, 27 Dec 2006) $"
  39. __cvsid__   = "$Id: tarfile.py 53162 2006-12-27 10:36:58Z lars.gustaebel $"
  40. __credits__ = "Gustavo Niemeyer, Niels GustΣbel, Richard Townsend."
  41.  
  42. #---------
  43. # Imports
  44. #---------
  45. import sys
  46. import os
  47. import shutil
  48. import stat
  49. import errno
  50. import time
  51. import struct
  52. import copy
  53.  
  54. if sys.platform == 'mac':
  55.     # This module needs work for MacOS9, especially in the area of pathname
  56.     # handling. In many places it is assumed a simple substitution of / by the
  57.     # local os.path.sep is good enough to convert pathnames, but this does not
  58.     # work with the mac rooted:path:name versus :nonrooted:path:name syntax
  59.     raise ImportError, "tarfile does not work for platform==mac"
  60.  
  61. try:
  62.     import grp, pwd
  63. except ImportError:
  64.     grp = pwd = None
  65.  
  66. # from tarfile import *
  67. __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"]
  68.  
  69. #---------------------------------------------------------
  70. # tar constants
  71. #---------------------------------------------------------
  72. NUL        = "\0"               # the null character
  73. BLOCKSIZE  = 512                # length of processing blocks
  74. RECORDSIZE = BLOCKSIZE * 20     # length of records
  75. MAGIC      = "ustar"            # magic tar string
  76. VERSION    = "00"               # version number
  77.  
  78. LENGTH_NAME    = 100            # maximum length of a filename
  79. LENGTH_LINK    = 100            # maximum length of a linkname
  80. LENGTH_PREFIX  = 155            # maximum length of the prefix field
  81. MAXSIZE_MEMBER = 077777777777L  # maximum size of a file (11 octal digits)
  82.  
  83. REGTYPE  = "0"                  # regular file
  84. AREGTYPE = "\0"                 # regular file
  85. LNKTYPE  = "1"                  # link (inside tarfile)
  86. SYMTYPE  = "2"                  # symbolic link
  87. CHRTYPE  = "3"                  # character special device
  88. BLKTYPE  = "4"                  # block special device
  89. DIRTYPE  = "5"                  # directory
  90. FIFOTYPE = "6"                  # fifo special device
  91. CONTTYPE = "7"                  # contiguous file
  92.  
  93. GNUTYPE_LONGNAME = "L"          # GNU tar extension for longnames
  94. GNUTYPE_LONGLINK = "K"          # GNU tar extension for longlink
  95. GNUTYPE_SPARSE   = "S"          # GNU tar extension for sparse file
  96.  
  97. #---------------------------------------------------------
  98. # tarfile constants
  99. #---------------------------------------------------------
  100. SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE,  # file types that tarfile
  101.                    SYMTYPE, DIRTYPE, FIFOTYPE,  # can cope with.
  102.                    CONTTYPE, CHRTYPE, BLKTYPE,
  103.                    GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
  104.                    GNUTYPE_SPARSE)
  105.  
  106. REGULAR_TYPES = (REGTYPE, AREGTYPE,             # file types that somehow
  107.                  CONTTYPE, GNUTYPE_SPARSE)      # represent regular files
  108.  
  109. #---------------------------------------------------------
  110. # Bits used in the mode field, values in octal.
  111. #---------------------------------------------------------
  112. S_IFLNK = 0120000        # symbolic link
  113. S_IFREG = 0100000        # regular file
  114. S_IFBLK = 0060000        # block device
  115. S_IFDIR = 0040000        # directory
  116. S_IFCHR = 0020000        # character device
  117. S_IFIFO = 0010000        # fifo
  118.  
  119. TSUID   = 04000          # set UID on execution
  120. TSGID   = 02000          # set GID on execution
  121. TSVTX   = 01000          # reserved
  122.  
  123. TUREAD  = 0400           # read by owner
  124. TUWRITE = 0200           # write by owner
  125. TUEXEC  = 0100           # execute/search by owner
  126. TGREAD  = 0040           # read by group
  127. TGWRITE = 0020           # write by group
  128. TGEXEC  = 0010           # execute/search by group
  129. TOREAD  = 0004           # read by other
  130. TOWRITE = 0002           # write by other
  131. TOEXEC  = 0001           # execute/search by other
  132.  
  133. #---------------------------------------------------------
  134. # Some useful functions
  135. #---------------------------------------------------------
  136.  
  137. def stn(s, length):
  138.     """Convert a python string to a null-terminated string buffer.
  139.     """
  140.     return s[:length] + (length - len(s)) * NUL
  141.  
  142. def nti(s):
  143.     """Convert a number field to a python number.
  144.     """
  145.     # There are two possible encodings for a number field, see
  146.     # itn() below.
  147.     if s[0] != chr(0200):
  148.         n = int(s.rstrip(NUL + " ") or "0", 8)
  149.     else:
  150.         n = 0L
  151.         for i in xrange(len(s) - 1):
  152.             n <<= 8
  153.             n += ord(s[i + 1])
  154.     return n
  155.  
  156. def itn(n, digits=8, posix=False):
  157.     """Convert a python number to a number field.
  158.     """
  159.     # POSIX 1003.1-1988 requires numbers to be encoded as a string of
  160.     # octal digits followed by a null-byte, this allows values up to
  161.     # (8**(digits-1))-1. GNU tar allows storing numbers greater than
  162.     # that if necessary. A leading 0200 byte indicates this particular
  163.     # encoding, the following digits-1 bytes are a big-endian
  164.     # representation. This allows values up to (256**(digits-1))-1.
  165.     if 0 <= n < 8 ** (digits - 1):
  166.         s = "%0*o" % (digits - 1, n) + NUL
  167.     else:
  168.         if posix:
  169.             raise ValueError("overflow in number field")
  170.  
  171.         if n < 0:
  172.             # XXX We mimic GNU tar's behaviour with negative numbers,
  173.             # this could raise OverflowError.
  174.             n = struct.unpack("L", struct.pack("l", n))[0]
  175.  
  176.         s = ""
  177.         for i in xrange(digits - 1):
  178.             s = chr(n & 0377) + s
  179.             n >>= 8
  180.         s = chr(0200) + s
  181.     return s
  182.  
  183. def calc_chksums(buf):
  184.     """Calculate the checksum for a member's header by summing up all
  185.        characters except for the chksum field which is treated as if
  186.        it was filled with spaces. According to the GNU tar sources,
  187.        some tars (Sun and NeXT) calculate chksum with signed char,
  188.        which will be different if there are chars in the buffer with
  189.        the high bit set. So we calculate two checksums, unsigned and
  190.        signed.
  191.     """
  192.     unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
  193.     signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
  194.     return unsigned_chksum, signed_chksum
  195.  
  196. def copyfileobj(src, dst, length=None):
  197.     """Copy length bytes from fileobj src to fileobj dst.
  198.        If length is None, copy the entire content.
  199.     """
  200.     if length == 0:
  201.         return
  202.     if length is None:
  203.         shutil.copyfileobj(src, dst)
  204.         return
  205.  
  206.     BUFSIZE = 16 * 1024
  207.     blocks, remainder = divmod(length, BUFSIZE)
  208.     for b in xrange(blocks):
  209.         buf = src.read(BUFSIZE)
  210.         if len(buf) < BUFSIZE:
  211.             raise IOError("end of file reached")
  212.         dst.write(buf)
  213.  
  214.     if remainder != 0:
  215.         buf = src.read(remainder)
  216.         if len(buf) < remainder:
  217.             raise IOError("end of file reached")
  218.         dst.write(buf)
  219.     return
  220.  
  221. filemode_table = (
  222.     ((S_IFLNK,      "l"),
  223.      (S_IFREG,      "-"),
  224.      (S_IFBLK,      "b"),
  225.      (S_IFDIR,      "d"),
  226.      (S_IFCHR,      "c"),
  227.      (S_IFIFO,      "p")),
  228.  
  229.     ((TUREAD,       "r"),),
  230.     ((TUWRITE,      "w"),),
  231.     ((TUEXEC|TSUID, "s"),
  232.      (TSUID,        "S"),
  233.      (TUEXEC,       "x")),
  234.  
  235.     ((TGREAD,       "r"),),
  236.     ((TGWRITE,      "w"),),
  237.     ((TGEXEC|TSGID, "s"),
  238.      (TSGID,        "S"),
  239.      (TGEXEC,       "x")),
  240.  
  241.     ((TOREAD,       "r"),),
  242.     ((TOWRITE,      "w"),),
  243.     ((TOEXEC|TSVTX, "t"),
  244.      (TSVTX,        "T"),
  245.      (TOEXEC,       "x"))
  246. )
  247.  
  248. def filemode(mode):
  249.     """Convert a file's mode to a string of the form
  250.        -rwxrwxrwx.
  251.        Used by TarFile.list()
  252.     """
  253.     perm = []
  254.     for table in filemode_table:
  255.         for bit, char in table:
  256.             if mode & bit == bit:
  257.                 perm.append(char)
  258.                 break
  259.         else:
  260.             perm.append("-")
  261.     return "".join(perm)
  262.  
  263. if os.sep != "/":
  264.     normpath = lambda path: os.path.normpath(path).replace(os.sep, "/")
  265. else:
  266.     normpath = os.path.normpath
  267.  
  268. class TarError(Exception):
  269.     """Base exception."""
  270.     pass
  271. class ExtractError(TarError):
  272.     """General exception for extract errors."""
  273.     pass
  274. class ReadError(TarError):
  275.     """Exception for unreadble tar archives."""
  276.     pass
  277. class CompressionError(TarError):
  278.     """Exception for unavailable compression methods."""
  279.     pass
  280. class StreamError(TarError):
  281.     """Exception for unsupported operations on stream-like TarFiles."""
  282.     pass
  283.  
  284. #---------------------------
  285. # internal stream interface
  286. #---------------------------
  287. class _LowLevelFile:
  288.     """Low-level file object. Supports reading and writing.
  289.        It is used instead of a regular file object for streaming
  290.        access.
  291.     """
  292.  
  293.     def __init__(self, name, mode):
  294.         mode = {
  295.             "r": os.O_RDONLY,
  296.             "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
  297.         }[mode]
  298.         if hasattr(os, "O_BINARY"):
  299.             mode |= os.O_BINARY
  300.         self.fd = os.open(name, mode)
  301.  
  302.     def close(self):
  303.         os.close(self.fd)
  304.  
  305.     def read(self, size):
  306.         return os.read(self.fd, size)
  307.  
  308.     def write(self, s):
  309.         os.write(self.fd, s)
  310.  
  311. class _Stream:
  312.     """Class that serves as an adapter between TarFile and
  313.        a stream-like object.  The stream-like object only
  314.        needs to have a read() or write() method and is accessed
  315.        blockwise.  Use of gzip or bzip2 compression is possible.
  316.        A stream-like object could be for example: sys.stdin,
  317.        sys.stdout, a socket, a tape device etc.
  318.  
  319.        _Stream is intended to be used only internally.
  320.     """
  321.  
  322.     def __init__(self, name, mode, comptype, fileobj, bufsize):
  323.         """Construct a _Stream object.
  324.         """
  325.         self._extfileobj = True
  326.         if fileobj is None:
  327.             fileobj = _LowLevelFile(name, mode)
  328.             self._extfileobj = False
  329.  
  330.         if comptype == '*':
  331.             # Enable transparent compression detection for the
  332.             # stream interface
  333.             fileobj = _StreamProxy(fileobj)
  334.             comptype = fileobj.getcomptype()
  335.  
  336.         self.name     = name or ""
  337.         self.mode     = mode
  338.         self.comptype = comptype
  339.         self.fileobj  = fileobj
  340.         self.bufsize  = bufsize
  341.         self.buf      = ""
  342.         self.pos      = 0L
  343.         self.closed   = False
  344.  
  345.         if comptype == "gz":
  346.             try:
  347.                 import zlib
  348.             except ImportError:
  349.                 raise CompressionError("zlib module is not available")
  350.             self.zlib = zlib
  351.             self.crc = zlib.crc32("")
  352.             if mode == "r":
  353.                 self._init_read_gz()
  354.             else:
  355.                 self._init_write_gz()
  356.  
  357.         if comptype == "bz2":
  358.             try:
  359.                 import bz2
  360.             except ImportError:
  361.                 raise CompressionError("bz2 module is not available")
  362.             if mode == "r":
  363.                 self.dbuf = ""
  364.                 self.cmp = bz2.BZ2Decompressor()
  365.             else:
  366.                 self.cmp = bz2.BZ2Compressor()
  367.  
  368.     def __del__(self):
  369.         if hasattr(self, "closed") and not self.closed:
  370.             self.close()
  371.  
  372.     def _init_write_gz(self):
  373.         """Initialize for writing with gzip compression.
  374.         """
  375.         self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED,
  376.                                             -self.zlib.MAX_WBITS,
  377.                                             self.zlib.DEF_MEM_LEVEL,
  378.                                             0)
  379.         timestamp = struct.pack("<L", long(time.time()))
  380.         self.__write("\037\213\010\010%s\002\377" % timestamp)
  381.         if self.name.endswith(".gz"):
  382.             self.name = self.name[:-3]
  383.         self.__write(self.name + NUL)
  384.  
  385.     def write(self, s):
  386.         """Write string s to the stream.
  387.         """
  388.         if self.comptype == "gz":
  389.             self.crc = self.zlib.crc32(s, self.crc)
  390.         self.pos += len(s)
  391.         if self.comptype != "tar":
  392.             s = self.cmp.compress(s)
  393.         self.__write(s)
  394.  
  395.     def __write(self, s):
  396.         """Write string s to the stream if a whole new block
  397.            is ready to be written.
  398.         """
  399.         self.buf += s
  400.         while len(self.buf) > self.bufsize:
  401.             self.fileobj.write(self.buf[:self.bufsize])
  402.             self.buf = self.buf[self.bufsize:]
  403.  
  404.     def close(self):
  405.         """Close the _Stream object. No operation should be
  406.            done on it afterwards.
  407.         """
  408.         if self.closed:
  409.             return
  410.  
  411.         if self.mode == "w" and self.comptype != "tar":
  412.             self.buf += self.cmp.flush()
  413.  
  414.         if self.mode == "w" and self.buf:
  415.             self.fileobj.write(self.buf)
  416.             self.buf = ""
  417.             if self.comptype == "gz":
  418.                 # The native zlib crc is an unsigned 32-bit integer, but
  419.                 # the Python wrapper implicitly casts that to a signed C
  420.                 # long.  So, on a 32-bit box self.crc may "look negative",
  421.                 # while the same crc on a 64-bit box may "look positive".
  422.                 # To avoid irksome warnings from the `struct` module, force
  423.                 # it to look positive on all boxes.
  424.                 self.fileobj.write(struct.pack("<L", self.crc & 0xffffffffL))
  425.                 self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFFL))
  426.  
  427.         if not self._extfileobj:
  428.             self.fileobj.close()
  429.  
  430.         self.closed = True
  431.  
  432.     def _init_read_gz(self):
  433.         """Initialize for reading a gzip compressed fileobj.
  434.         """
  435.         self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
  436.         self.dbuf = ""
  437.  
  438.         # taken from gzip.GzipFile with some alterations
  439.         if self.__read(2) != "\037\213":
  440.             raise ReadError("not a gzip file")
  441.         if self.__read(1) != "\010":
  442.             raise CompressionError("unsupported compression method")
  443.  
  444.         flag = ord(self.__read(1))
  445.         self.__read(6)
  446.  
  447.         if flag & 4:
  448.             xlen = ord(self.__read(1)) + 256 * ord(self.__read(1))
  449.             self.read(xlen)
  450.         if flag & 8:
  451.             while True:
  452.                 s = self.__read(1)
  453.                 if not s or s == NUL:
  454.                     break
  455.         if flag & 16:
  456.             while True:
  457.                 s = self.__read(1)
  458.                 if not s or s == NUL:
  459.                     break
  460.         if flag & 2:
  461.             self.__read(2)
  462.  
  463.     def tell(self):
  464.         """Return the stream's file pointer position.
  465.         """
  466.         return self.pos
  467.  
  468.     def seek(self, pos=0):
  469.         """Set the stream's file pointer to pos. Negative seeking
  470.            is forbidden.
  471.         """
  472.         if pos - self.pos >= 0:
  473.             blocks, remainder = divmod(pos - self.pos, self.bufsize)
  474.             for i in xrange(blocks):
  475.                 self.read(self.bufsize)
  476.             self.read(remainder)
  477.         else:
  478.             raise StreamError("seeking backwards is not allowed")
  479.         return self.pos
  480.  
  481.     def read(self, size=None):
  482.         """Return the next size number of bytes from the stream.
  483.            If size is not defined, return all bytes of the stream
  484.            up to EOF.
  485.         """
  486.         if size is None:
  487.             t = []
  488.             while True:
  489.                 buf = self._read(self.bufsize)
  490.                 if not buf:
  491.                     break
  492.                 t.append(buf)
  493.             buf = "".join(t)
  494.         else:
  495.             buf = self._read(size)
  496.         self.pos += len(buf)
  497.         return buf
  498.  
  499.     def _read(self, size):
  500.         """Return size bytes from the stream.
  501.         """
  502.         if self.comptype == "tar":
  503.             return self.__read(size)
  504.  
  505.         c = len(self.dbuf)
  506.         t = [self.dbuf]
  507.         while c < size:
  508.             buf = self.__read(self.bufsize)
  509.             if not buf:
  510.                 break
  511.             buf = self.cmp.decompress(buf)
  512.             t.append(buf)
  513.             c += len(buf)
  514.         t = "".join(t)
  515.         self.dbuf = t[size:]
  516.         return t[:size]
  517.  
  518.     def __read(self, size):
  519.         """Return size bytes from stream. If internal buffer is empty,
  520.            read another block from the stream.
  521.         """
  522.         c = len(self.buf)
  523.         t = [self.buf]
  524.         while c < size:
  525.             buf = self.fileobj.read(self.bufsize)
  526.             if not buf:
  527.                 break
  528.             t.append(buf)
  529.             c += len(buf)
  530.         t = "".join(t)
  531.         self.buf = t[size:]
  532.         return t[:size]
  533. # class _Stream
  534.  
  535. class _StreamProxy(object):
  536.     """Small proxy class that enables transparent compression
  537.        detection for the Stream interface (mode 'r|*').
  538.     """
  539.  
  540.     def __init__(self, fileobj):
  541.         self.fileobj = fileobj
  542.         self.buf = self.fileobj.read(BLOCKSIZE)
  543.  
  544.     def read(self, size):
  545.         self.read = self.fileobj.read
  546.         return self.buf
  547.  
  548.     def getcomptype(self):
  549.         if self.buf.startswith("\037\213\010"):
  550.             return "gz"
  551.         if self.buf.startswith("BZh91"):
  552.             return "bz2"
  553.         return "tar"
  554.  
  555.     def close(self):
  556.         self.fileobj.close()
  557. # class StreamProxy
  558.  
  559. class _BZ2Proxy(object):
  560.     """Small proxy class that enables external file object
  561.        support for "r:bz2" and "w:bz2" modes. This is actually
  562.        a workaround for a limitation in bz2 module's BZ2File
  563.        class which (unlike gzip.GzipFile) has no support for
  564.        a file object argument.
  565.     """
  566.  
  567.     blocksize = 16 * 1024
  568.  
  569.     def __init__(self, fileobj, mode):
  570.         self.fileobj = fileobj
  571.         self.mode = mode
  572.         self.init()
  573.  
  574.     def init(self):
  575.         import bz2
  576.         self.pos = 0
  577.         if self.mode == "r":
  578.             self.bz2obj = bz2.BZ2Decompressor()
  579.             self.fileobj.seek(0)
  580.             self.buf = ""
  581.         else:
  582.             self.bz2obj = bz2.BZ2Compressor()
  583.  
  584.     def read(self, size):
  585.         b = [self.buf]
  586.         x = len(self.buf)
  587.         while x < size:
  588.             try:
  589.                 raw = self.fileobj.read(self.blocksize)
  590.                 data = self.bz2obj.decompress(raw)
  591.                 b.append(data)
  592.             except EOFError:
  593.                 break
  594.             x += len(data)
  595.         self.buf = "".join(b)
  596.  
  597.         buf = self.buf[:size]
  598.         self.buf = self.buf[size:]
  599.         self.pos += len(buf)
  600.         return buf
  601.  
  602.     def seek(self, pos):
  603.         if pos < self.pos:
  604.             self.init()
  605.         self.read(pos - self.pos)
  606.  
  607.     def tell(self):
  608.         return self.pos
  609.  
  610.     def write(self, data):
  611.         self.pos += len(data)
  612.         raw = self.bz2obj.compress(data)
  613.         self.fileobj.write(raw)
  614.  
  615.     def close(self):
  616.         if self.mode == "w":
  617.             raw = self.bz2obj.flush()
  618.             self.fileobj.write(raw)
  619.         self.fileobj.close()
  620. # class _BZ2Proxy
  621.  
  622. #------------------------
  623. # Extraction file object
  624. #------------------------
  625. class _FileInFile(object):
  626.     """A thin wrapper around an existing file object that
  627.        provides a part of its data as an individual file
  628.        object.
  629.     """
  630.  
  631.     def __init__(self, fileobj, offset, size, sparse=None):
  632.         self.fileobj = fileobj
  633.         self.offset = offset
  634.         self.size = size
  635.         self.sparse = sparse
  636.         self.position = 0
  637.  
  638.     def tell(self):
  639.         """Return the current file position.
  640.         """
  641.         return self.position
  642.  
  643.     def seek(self, position):
  644.         """Seek to a position in the file.
  645.         """
  646.         self.position = position
  647.  
  648.     def read(self, size=None):
  649.         """Read data from the file.
  650.         """
  651.         if size is None:
  652.             size = self.size - self.position
  653.         else:
  654.             size = min(size, self.size - self.position)
  655.  
  656.         if self.sparse is None:
  657.             return self.readnormal(size)
  658.         else:
  659.             return self.readsparse(size)
  660.  
  661.     def readnormal(self, size):
  662.         """Read operation for regular files.
  663.         """
  664.         self.fileobj.seek(self.offset + self.position)
  665.         self.position += size
  666.         return self.fileobj.read(size)
  667.  
  668.     def readsparse(self, size):
  669.         """Read operation for sparse files.
  670.         """
  671.         data = []
  672.         while size > 0:
  673.             buf = self.readsparsesection(size)
  674.             if not buf:
  675.                 break
  676.             size -= len(buf)
  677.             data.append(buf)
  678.         return "".join(data)
  679.  
  680.     def readsparsesection(self, size):
  681.         """Read a single section of a sparse file.
  682.         """
  683.         section = self.sparse.find(self.position)
  684.  
  685.         if section is None:
  686.             return ""
  687.  
  688.         size = min(size, section.offset + section.size - self.position)
  689.  
  690.         if isinstance(section, _data):
  691.             realpos = section.realpos + self.position - section.offset
  692.             self.fileobj.seek(self.offset + realpos)
  693.             self.position += size
  694.             return self.fileobj.read(size)
  695.         else:
  696.             self.position += size
  697.             return NUL * size
  698. #class _FileInFile
  699.  
  700.  
  701. class ExFileObject(object):
  702.     """File-like object for reading an archive member.
  703.        Is returned by TarFile.extractfile().
  704.     """
  705.     blocksize = 1024
  706.  
  707.     def __init__(self, tarfile, tarinfo):
  708.         self.fileobj = _FileInFile(tarfile.fileobj,
  709.                                    tarinfo.offset_data,
  710.                                    tarinfo.size,
  711.                                    getattr(tarinfo, "sparse", None))
  712.         self.name = tarinfo.name
  713.         self.mode = "r"
  714.         self.closed = False
  715.         self.size = tarinfo.size
  716.  
  717.         self.position = 0
  718.         self.buffer = ""
  719.  
  720.     def read(self, size=None):
  721.         """Read at most size bytes from the file. If size is not
  722.            present or None, read all data until EOF is reached.
  723.         """
  724.         if self.closed:
  725.             raise ValueError("I/O operation on closed file")
  726.  
  727.         buf = ""
  728.         if self.buffer:
  729.             if size is None:
  730.                 buf = self.buffer
  731.                 self.buffer = ""
  732.             else:
  733.                 buf = self.buffer[:size]
  734.                 self.buffer = self.buffer[size:]
  735.  
  736.         if size is None:
  737.             buf += self.fileobj.read()
  738.         else:
  739.             buf += self.fileobj.read(size - len(buf))
  740.  
  741.         self.position += len(buf)
  742.         return buf
  743.  
  744.     def readline(self, size=-1):
  745.         """Read one entire line from the file. If size is present
  746.            and non-negative, return a string with at most that
  747.            size, which may be an incomplete line.
  748.         """
  749.         if self.closed:
  750.             raise ValueError("I/O operation on closed file")
  751.  
  752.         if "\n" in self.buffer:
  753.             pos = self.buffer.find("\n") + 1
  754.         else:
  755.             buffers = [self.buffer]
  756.             while True:
  757.                 buf = self.fileobj.read(self.blocksize)
  758.                 buffers.append(buf)
  759.                 if not buf or "\n" in buf:
  760.                     self.buffer = "".join(buffers)
  761.                     pos = self.buffer.find("\n") + 1
  762.                     if pos == 0:
  763.                         # no newline found.
  764.                         pos = len(self.buffer)
  765.                     break
  766.  
  767.         if size != -1:
  768.             pos = min(size, pos)
  769.  
  770.         buf = self.buffer[:pos]
  771.         self.buffer = self.buffer[pos:]
  772.         self.position += len(buf)
  773.         return buf
  774.  
  775.     def readlines(self):
  776.         """Return a list with all remaining lines.
  777.         """
  778.         result = []
  779.         while True:
  780.             line = self.readline()
  781.             if not line: break
  782.             result.append(line)
  783.         return result
  784.  
  785.     def tell(self):
  786.         """Return the current file position.
  787.         """
  788.         if self.closed:
  789.             raise ValueError("I/O operation on closed file")
  790.  
  791.         return self.position
  792.  
  793.     def seek(self, pos, whence=os.SEEK_SET):
  794.         """Seek to a position in the file.
  795.         """
  796.         if self.closed:
  797.             raise ValueError("I/O operation on closed file")
  798.  
  799.         if whence == os.SEEK_SET:
  800.             self.position = min(max(pos, 0), self.size)
  801.         elif whence == os.SEEK_CUR:
  802.             if pos < 0:
  803.                 self.position = max(self.position + pos, 0)
  804.             else:
  805.                 self.position = min(self.position + pos, self.size)
  806.         elif whence == os.SEEK_END:
  807.             self.position = max(min(self.size + pos, self.size), 0)
  808.         else:
  809.             raise ValueError("Invalid argument")
  810.  
  811.         self.buffer = ""
  812.         self.fileobj.seek(self.position)
  813.  
  814.     def close(self):
  815.         """Close the file object.
  816.         """
  817.         self.closed = True
  818.  
  819.     def __iter__(self):
  820.         """Get an iterator over the file's lines.
  821.         """
  822.         while True:
  823.             line = self.readline()
  824.             if not line:
  825.                 break
  826.             yield line
  827. #class ExFileObject
  828.  
  829. #------------------
  830. # Exported Classes
  831. #------------------
  832. class TarInfo(object):
  833.     """Informational class which holds the details about an
  834.        archive member given by a tar header block.
  835.        TarInfo objects are returned by TarFile.getmember(),
  836.        TarFile.getmembers() and TarFile.gettarinfo() and are
  837.        usually created internally.
  838.     """
  839.  
  840.     def __init__(self, name=""):
  841.         """Construct a TarInfo object. name is the optional name
  842.            of the member.
  843.         """
  844.         self.name = name        # member name (dirnames must end with '/')
  845.         self.mode = 0666        # file permissions
  846.         self.uid = 0            # user id
  847.         self.gid = 0            # group id
  848.         self.size = 0           # file size
  849.         self.mtime = 0          # modification time
  850.         self.chksum = 0         # header checksum
  851.         self.type = REGTYPE     # member type
  852.         self.linkname = ""      # link name
  853.         self.uname = "user"     # user name
  854.         self.gname = "group"    # group name
  855.         self.devmajor = 0       # device major number
  856.         self.devminor = 0       # device minor number
  857.  
  858.         self.offset = 0         # the tar header starts here
  859.         self.offset_data = 0    # the file's data starts here
  860.  
  861.     def __repr__(self):
  862.         return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
  863.  
  864.     @classmethod
  865.     def frombuf(cls, buf):
  866.         """Construct a TarInfo object from a 512 byte string buffer.
  867.         """
  868.         if len(buf) != BLOCKSIZE:
  869.             raise ValueError("truncated header")
  870.         if buf.count(NUL) == BLOCKSIZE:
  871.             raise ValueError("empty header")
  872.  
  873.         tarinfo = cls()
  874.         tarinfo.buf = buf
  875.         tarinfo.name = buf[0:100].rstrip(NUL)
  876.         tarinfo.mode = nti(buf[100:108])
  877.         tarinfo.uid = nti(buf[108:116])
  878.         tarinfo.gid = nti(buf[116:124])
  879.         tarinfo.size = nti(buf[124:136])
  880.         tarinfo.mtime = nti(buf[136:148])
  881.         tarinfo.chksum = nti(buf[148:156])
  882.         tarinfo.type = buf[156:157]
  883.         tarinfo.linkname = buf[157:257].rstrip(NUL)
  884.         tarinfo.uname = buf[265:297].rstrip(NUL)
  885.         tarinfo.gname = buf[297:329].rstrip(NUL)
  886.         tarinfo.devmajor = nti(buf[329:337])
  887.         tarinfo.devminor = nti(buf[337:345])
  888.         prefix = buf[345:500].rstrip(NUL)
  889.  
  890.         if prefix and not tarinfo.issparse():
  891.             tarinfo.name = prefix + "/" + tarinfo.name
  892.  
  893.         if tarinfo.chksum not in calc_chksums(buf):
  894.             raise ValueError("invalid header")
  895.         return tarinfo
  896.  
  897.     def tobuf(self, posix=False):
  898.         """Return a tar header as a string of 512 byte blocks.
  899.         """
  900.         buf = ""
  901.         type = self.type
  902.         prefix = ""
  903.  
  904.         if self.name.endswith("/"):
  905.             type = DIRTYPE
  906.  
  907.         if type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  908.             # Prevent "././@LongLink" from being normalized.
  909.             name = self.name
  910.         else:
  911.             name = normpath(self.name)
  912.  
  913.         if type == DIRTYPE:
  914.             # directories should end with '/'
  915.             name += "/"
  916.  
  917.         linkname = self.linkname
  918.         if linkname:
  919.             # if linkname is empty we end up with a '.'
  920.             linkname = normpath(linkname)
  921.  
  922.         if posix:
  923.             if self.size > MAXSIZE_MEMBER:
  924.                 raise ValueError("file is too large (>= 8 GB)")
  925.  
  926.             if len(self.linkname) > LENGTH_LINK:
  927.                 raise ValueError("linkname is too long (>%d)" % (LENGTH_LINK))
  928.  
  929.             if len(name) > LENGTH_NAME:
  930.                 prefix = name[:LENGTH_PREFIX + 1]
  931.                 while prefix and prefix[-1] != "/":
  932.                     prefix = prefix[:-1]
  933.  
  934.                 name = name[len(prefix):]
  935.                 prefix = prefix[:-1]
  936.  
  937.                 if not prefix or len(name) > LENGTH_NAME:
  938.                     raise ValueError("name is too long")
  939.  
  940.         else:
  941.             if len(self.linkname) > LENGTH_LINK:
  942.                 buf += self._create_gnulong(self.linkname, GNUTYPE_LONGLINK)
  943.  
  944.             if len(name) > LENGTH_NAME:
  945.                 buf += self._create_gnulong(name, GNUTYPE_LONGNAME)
  946.  
  947.         parts = [
  948.             stn(name, 100),
  949.             itn(self.mode & 07777, 8, posix),
  950.             itn(self.uid, 8, posix),
  951.             itn(self.gid, 8, posix),
  952.             itn(self.size, 12, posix),
  953.             itn(self.mtime, 12, posix),
  954.             "        ", # checksum field
  955.             type,
  956.             stn(self.linkname, 100),
  957.             stn(MAGIC, 6),
  958.             stn(VERSION, 2),
  959.             stn(self.uname, 32),
  960.             stn(self.gname, 32),
  961.             itn(self.devmajor, 8, posix),
  962.             itn(self.devminor, 8, posix),
  963.             stn(prefix, 155)
  964.         ]
  965.  
  966.         buf += struct.pack("%ds" % BLOCKSIZE, "".join(parts))
  967.         chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
  968.         buf = buf[:-364] + "%06o\0" % chksum + buf[-357:]
  969.         self.buf = buf
  970.         return buf
  971.  
  972.     def _create_gnulong(self, name, type):
  973.         """Create a GNU longname/longlink header from name.
  974.            It consists of an extended tar header, with the length
  975.            of the longname as size, followed by data blocks,
  976.            which contain the longname as a null terminated string.
  977.         """
  978.         name += NUL
  979.  
  980.         tarinfo = self.__class__()
  981.         tarinfo.name = "././@LongLink"
  982.         tarinfo.type = type
  983.         tarinfo.mode = 0
  984.         tarinfo.size = len(name)
  985.  
  986.         # create extended header
  987.         buf = tarinfo.tobuf()
  988.         # create name blocks
  989.         buf += name
  990.         blocks, remainder = divmod(len(name), BLOCKSIZE)
  991.         if remainder > 0:
  992.             buf += (BLOCKSIZE - remainder) * NUL
  993.         return buf
  994.  
  995.     def isreg(self):
  996.         return self.type in REGULAR_TYPES
  997.     def isfile(self):
  998.         return self.isreg()
  999.     def isdir(self):
  1000.         return self.type == DIRTYPE
  1001.     def issym(self):
  1002.         return self.type == SYMTYPE
  1003.     def islnk(self):
  1004.         return self.type == LNKTYPE
  1005.     def ischr(self):
  1006.         return self.type == CHRTYPE
  1007.     def isblk(self):
  1008.         return self.type == BLKTYPE
  1009.     def isfifo(self):
  1010.         return self.type == FIFOTYPE
  1011.     def issparse(self):
  1012.         return self.type == GNUTYPE_SPARSE
  1013.     def isdev(self):
  1014.         return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
  1015. # class TarInfo
  1016.  
  1017. class TarFile(object):
  1018.     """The TarFile Class provides an interface to tar archives.
  1019.     """
  1020.  
  1021.     debug = 0                   # May be set from 0 (no msgs) to 3 (all msgs)
  1022.  
  1023.     dereference = False         # If true, add content of linked file to the
  1024.                                 # tar file, else the link.
  1025.  
  1026.     ignore_zeros = False        # If true, skips empty or invalid blocks and
  1027.                                 # continues processing.
  1028.  
  1029.     errorlevel = 0              # If 0, fatal errors only appear in debug
  1030.                                 # messages (if debug >= 0). If > 0, errors
  1031.                                 # are passed to the caller as exceptions.
  1032.  
  1033.     posix = False               # If True, generates POSIX.1-1990-compliant
  1034.                                 # archives (no GNU extensions!)
  1035.  
  1036.     fileobject = ExFileObject
  1037.  
  1038.     def __init__(self, name=None, mode="r", fileobj=None):
  1039.         """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
  1040.            read from an existing archive, 'a' to append data to an existing
  1041.            file or 'w' to create a new file overwriting an existing one. `mode'
  1042.            defaults to 'r'.
  1043.            If `fileobj' is given, it is used for reading or writing data. If it
  1044.            can be determined, `mode' is overridden by `fileobj's mode.
  1045.            `fileobj' is not closed, when TarFile is closed.
  1046.         """
  1047.         self.name = os.path.abspath(name)
  1048.  
  1049.         if len(mode) > 1 or mode not in "raw":
  1050.             raise ValueError("mode must be 'r', 'a' or 'w'")
  1051.         self._mode = mode
  1052.         self.mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
  1053.  
  1054.         if not fileobj:
  1055.             fileobj = file(self.name, self.mode)
  1056.             self._extfileobj = False
  1057.         else:
  1058.             if self.name is None and hasattr(fileobj, "name"):
  1059.                 self.name = os.path.abspath(fileobj.name)
  1060.             if hasattr(fileobj, "mode"):
  1061.                 self.mode = fileobj.mode
  1062.             self._extfileobj = True
  1063.         self.fileobj = fileobj
  1064.  
  1065.         # Init datastructures
  1066.         self.closed = False
  1067.         self.members = []       # list of members as TarInfo objects
  1068.         self._loaded = False    # flag if all members have been read
  1069.         self.offset = 0L        # current position in the archive file
  1070.         self.inodes = {}        # dictionary caching the inodes of
  1071.                                 # archive members already added
  1072.  
  1073.         if self._mode == "r":
  1074.             self.firstmember = None
  1075.             self.firstmember = self.next()
  1076.  
  1077.         if self._mode == "a":
  1078.             # Move to the end of the archive,
  1079.             # before the first empty block.
  1080.             self.firstmember = None
  1081.             while True:
  1082.                 try:
  1083.                     tarinfo = self.next()
  1084.                 except ReadError:
  1085.                     self.fileobj.seek(0)
  1086.                     break
  1087.                 if tarinfo is None:
  1088.                     self.fileobj.seek(- BLOCKSIZE, 1)
  1089.                     break
  1090.  
  1091.         if self._mode in "aw":
  1092.             self._loaded = True
  1093.  
  1094.     #--------------------------------------------------------------------------
  1095.     # Below are the classmethods which act as alternate constructors to the
  1096.     # TarFile class. The open() method is the only one that is needed for
  1097.     # public use; it is the "super"-constructor and is able to select an
  1098.     # adequate "sub"-constructor for a particular compression using the mapping
  1099.     # from OPEN_METH.
  1100.     #
  1101.     # This concept allows one to subclass TarFile without losing the comfort of
  1102.     # the super-constructor. A sub-constructor is registered and made available
  1103.     # by adding it to the mapping in OPEN_METH.
  1104.  
  1105.     @classmethod
  1106.     def open(cls, name=None, mode="r", fileobj=None, bufsize=20*512):
  1107.         """Open a tar archive for reading, writing or appending. Return
  1108.            an appropriate TarFile class.
  1109.  
  1110.            mode:
  1111.            'r' or 'r:*' open for reading with transparent compression
  1112.            'r:'         open for reading exclusively uncompressed
  1113.            'r:gz'       open for reading with gzip compression
  1114.            'r:bz2'      open for reading with bzip2 compression
  1115.            'a' or 'a:'  open for appending
  1116.            'w' or 'w:'  open for writing without compression
  1117.            'w:gz'       open for writing with gzip compression
  1118.            'w:bz2'      open for writing with bzip2 compression
  1119.  
  1120.            'r|*'        open a stream of tar blocks with transparent compression
  1121.            'r|'         open an uncompressed stream of tar blocks for reading
  1122.            'r|gz'       open a gzip compressed stream of tar blocks
  1123.            'r|bz2'      open a bzip2 compressed stream of tar blocks
  1124.            'w|'         open an uncompressed stream for writing
  1125.            'w|gz'       open a gzip compressed stream for writing
  1126.            'w|bz2'      open a bzip2 compressed stream for writing
  1127.         """
  1128.  
  1129.         if not name and not fileobj:
  1130.             raise ValueError("nothing to open")
  1131.  
  1132.         if mode in ("r", "r:*"):
  1133.             # Find out which *open() is appropriate for opening the file.
  1134.             for comptype in cls.OPEN_METH:
  1135.                 func = getattr(cls, cls.OPEN_METH[comptype])
  1136.                 if fileobj is not None:
  1137.                     saved_pos = fileobj.tell()
  1138.                 try:
  1139.                     return func(name, "r", fileobj)
  1140.                 except (ReadError, CompressionError):
  1141.                     if fileobj is not None:
  1142.                         fileobj.seek(saved_pos)
  1143.                     continue
  1144.             raise ReadError("file could not be opened successfully")
  1145.  
  1146.         elif ":" in mode:
  1147.             filemode, comptype = mode.split(":", 1)
  1148.             filemode = filemode or "r"
  1149.             comptype = comptype or "tar"
  1150.  
  1151.             # Select the *open() function according to
  1152.             # given compression.
  1153.             if comptype in cls.OPEN_METH:
  1154.                 func = getattr(cls, cls.OPEN_METH[comptype])
  1155.             else:
  1156.                 raise CompressionError("unknown compression type %r" % comptype)
  1157.             return func(name, filemode, fileobj)
  1158.  
  1159.         elif "|" in mode:
  1160.             filemode, comptype = mode.split("|", 1)
  1161.             filemode = filemode or "r"
  1162.             comptype = comptype or "tar"
  1163.  
  1164.             if filemode not in "rw":
  1165.                 raise ValueError("mode must be 'r' or 'w'")
  1166.  
  1167.             t = cls(name, filemode,
  1168.                     _Stream(name, filemode, comptype, fileobj, bufsize))
  1169.             t._extfileobj = False
  1170.             return t
  1171.  
  1172.         elif mode in "aw":
  1173.             return cls.taropen(name, mode, fileobj)
  1174.  
  1175.         raise ValueError("undiscernible mode")
  1176.  
  1177.     @classmethod
  1178.     def taropen(cls, name, mode="r", fileobj=None):
  1179.         """Open uncompressed tar archive name for reading or writing.
  1180.         """
  1181.         if len(mode) > 1 or mode not in "raw":
  1182.             raise ValueError("mode must be 'r', 'a' or 'w'")
  1183.         return cls(name, mode, fileobj)
  1184.  
  1185.     @classmethod
  1186.     def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9):
  1187.         """Open gzip compressed tar archive name for reading or writing.
  1188.            Appending is not allowed.
  1189.         """
  1190.         if len(mode) > 1 or mode not in "rw":
  1191.             raise ValueError("mode must be 'r' or 'w'")
  1192.  
  1193.         try:
  1194.             import gzip
  1195.             gzip.GzipFile
  1196.         except (ImportError, AttributeError):
  1197.             raise CompressionError("gzip module is not available")
  1198.  
  1199.         if fileobj is None:
  1200.             fileobj = file(name, mode + "b")
  1201.  
  1202.         try:
  1203.             t = cls.taropen(name, mode,
  1204.                 gzip.GzipFile(name, mode, compresslevel, fileobj))
  1205.         except IOError:
  1206.             raise ReadError("not a gzip file")
  1207.         t._extfileobj = False
  1208.         return t
  1209.  
  1210.     @classmethod
  1211.     def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9):
  1212.         """Open bzip2 compressed tar archive name for reading or writing.
  1213.            Appending is not allowed.
  1214.         """
  1215.         if len(mode) > 1 or mode not in "rw":
  1216.             raise ValueError("mode must be 'r' or 'w'.")
  1217.  
  1218.         try:
  1219.             import bz2
  1220.         except ImportError:
  1221.             raise CompressionError("bz2 module is not available")
  1222.  
  1223.         if fileobj is not None:
  1224.             fileobj = _BZ2Proxy(fileobj, mode)
  1225.         else:
  1226.             fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
  1227.  
  1228.         try:
  1229.             t = cls.taropen(name, mode, fileobj)
  1230.         except IOError:
  1231.             raise ReadError("not a bzip2 file")
  1232.         t._extfileobj = False
  1233.         return t
  1234.  
  1235.     # All *open() methods are registered here.
  1236.     OPEN_METH = {
  1237.         "tar": "taropen",   # uncompressed tar
  1238.         "gz":  "gzopen",    # gzip compressed tar
  1239.         "bz2": "bz2open"    # bzip2 compressed tar
  1240.     }
  1241.  
  1242.     #--------------------------------------------------------------------------
  1243.     # The public methods which TarFile provides:
  1244.  
  1245.     def close(self):
  1246.         """Close the TarFile. In write-mode, two finishing zero blocks are
  1247.            appended to the archive.
  1248.         """
  1249.         if self.closed:
  1250.             return
  1251.  
  1252.         if self._mode in "aw":
  1253.             self.fileobj.write(NUL * (BLOCKSIZE * 2))
  1254.             self.offset += (BLOCKSIZE * 2)
  1255.             # fill up the end with zero-blocks
  1256.             # (like option -b20 for tar does)
  1257.             blocks, remainder = divmod(self.offset, RECORDSIZE)
  1258.             if remainder > 0:
  1259.                 self.fileobj.write(NUL * (RECORDSIZE - remainder))
  1260.  
  1261.         if not self._extfileobj:
  1262.             self.fileobj.close()
  1263.         self.closed = True
  1264.  
  1265.     def getmember(self, name):
  1266.         """Return a TarInfo object for member `name'. If `name' can not be
  1267.            found in the archive, KeyError is raised. If a member occurs more
  1268.            than once in the archive, its last occurence is assumed to be the
  1269.            most up-to-date version.
  1270.         """
  1271.         tarinfo = self._getmember(name)
  1272.         if tarinfo is None:
  1273.             raise KeyError("filename %r not found" % name)
  1274.         return tarinfo
  1275.  
  1276.     def getmembers(self):
  1277.         """Return the members of the archive as a list of TarInfo objects. The
  1278.            list has the same order as the members in the archive.
  1279.         """
  1280.         self._check()
  1281.         if not self._loaded:    # if we want to obtain a list of
  1282.             self._load()        # all members, we first have to
  1283.                                 # scan the whole archive.
  1284.         return self.members
  1285.  
  1286.     def getnames(self):
  1287.         """Return the members of the archive as a list of their names. It has
  1288.            the same order as the list returned by getmembers().
  1289.         """
  1290.         return [tarinfo.name for tarinfo in self.getmembers()]
  1291.  
  1292.     def gettarinfo(self, name=None, arcname=None, fileobj=None):
  1293.         """Create a TarInfo object for either the file `name' or the file
  1294.            object `fileobj' (using os.fstat on its file descriptor). You can
  1295.            modify some of the TarInfo's attributes before you add it using
  1296.            addfile(). If given, `arcname' specifies an alternative name for the
  1297.            file in the archive.
  1298.         """
  1299.         self._check("aw")
  1300.  
  1301.         # When fileobj is given, replace name by
  1302.         # fileobj's real name.
  1303.         if fileobj is not None:
  1304.             name = fileobj.name
  1305.  
  1306.         # Building the name of the member in the archive.
  1307.         # Backward slashes are converted to forward slashes,
  1308.         # Absolute paths are turned to relative paths.
  1309.         if arcname is None:
  1310.             arcname = name
  1311.         arcname = normpath(arcname)
  1312.         drv, arcname = os.path.splitdrive(arcname)
  1313.         while arcname[0:1] == "/":
  1314.             arcname = arcname[1:]
  1315.  
  1316.         # Now, fill the TarInfo object with
  1317.         # information specific for the file.
  1318.         tarinfo = TarInfo()
  1319.  
  1320.         # Use os.stat or os.lstat, depending on platform
  1321.         # and if symlinks shall be resolved.
  1322.         if fileobj is None:
  1323.             if hasattr(os, "lstat") and not self.dereference:
  1324.                 statres = os.lstat(name)
  1325.             else:
  1326.                 statres = os.stat(name)
  1327.         else:
  1328.             statres = os.fstat(fileobj.fileno())
  1329.         linkname = ""
  1330.  
  1331.         stmd = statres.st_mode
  1332.         if stat.S_ISREG(stmd):
  1333.             inode = (statres.st_ino, statres.st_dev)
  1334.             if not self.dereference and \
  1335.                     statres.st_nlink > 1 and inode in self.inodes:
  1336.                 # Is it a hardlink to an already
  1337.                 # archived file?
  1338.                 type = LNKTYPE
  1339.                 linkname = self.inodes[inode]
  1340.             else:
  1341.                 # The inode is added only if its valid.
  1342.                 # For win32 it is always 0.
  1343.                 type = REGTYPE
  1344.                 if inode[0]:
  1345.                     self.inodes[inode] = arcname
  1346.         elif stat.S_ISDIR(stmd):
  1347.             type = DIRTYPE
  1348.             if arcname[-1:] != "/":
  1349.                 arcname += "/"
  1350.         elif stat.S_ISFIFO(stmd):
  1351.             type = FIFOTYPE
  1352.         elif stat.S_ISLNK(stmd):
  1353.             type = SYMTYPE
  1354.             linkname = os.readlink(name)
  1355.         elif stat.S_ISCHR(stmd):
  1356.             type = CHRTYPE
  1357.         elif stat.S_ISBLK(stmd):
  1358.             type = BLKTYPE
  1359.         else:
  1360.             return None
  1361.  
  1362.         # Fill the TarInfo object with all
  1363.         # information we can get.
  1364.         tarinfo.name = arcname
  1365.         tarinfo.mode = stmd
  1366.         tarinfo.uid = statres.st_uid
  1367.         tarinfo.gid = statres.st_gid
  1368.         if stat.S_ISREG(stmd):
  1369.             tarinfo.size = statres.st_size
  1370.         else:
  1371.             tarinfo.size = 0L
  1372.         tarinfo.mtime = statres.st_mtime
  1373.         tarinfo.type = type
  1374.         tarinfo.linkname = linkname
  1375.         if pwd:
  1376.             try:
  1377.                 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
  1378.             except KeyError:
  1379.                 pass
  1380.         if grp:
  1381.             try:
  1382.                 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
  1383.             except KeyError:
  1384.                 pass
  1385.  
  1386.         if type in (CHRTYPE, BLKTYPE):
  1387.             if hasattr(os, "major") and hasattr(os, "minor"):
  1388.                 tarinfo.devmajor = os.major(statres.st_rdev)
  1389.                 tarinfo.devminor = os.minor(statres.st_rdev)
  1390.         return tarinfo
  1391.  
  1392.     def list(self, verbose=True):
  1393.         """Print a table of contents to sys.stdout. If `verbose' is False, only
  1394.            the names of the members are printed. If it is True, an `ls -l'-like
  1395.            output is produced.
  1396.         """
  1397.         self._check()
  1398.  
  1399.         for tarinfo in self:
  1400.             if verbose:
  1401.                 print filemode(tarinfo.mode),
  1402.                 print "%s/%s" % (tarinfo.uname or tarinfo.uid,
  1403.                                  tarinfo.gname or tarinfo.gid),
  1404.                 if tarinfo.ischr() or tarinfo.isblk():
  1405.                     print "%10s" % ("%d,%d" \
  1406.                                     % (tarinfo.devmajor, tarinfo.devminor)),
  1407.                 else:
  1408.                     print "%10d" % tarinfo.size,
  1409.                 print "%d-%02d-%02d %02d:%02d:%02d" \
  1410.                       % time.localtime(tarinfo.mtime)[:6],
  1411.  
  1412.             print tarinfo.name,
  1413.  
  1414.             if verbose:
  1415.                 if tarinfo.issym():
  1416.                     print "->", tarinfo.linkname,
  1417.                 if tarinfo.islnk():
  1418.                     print "link to", tarinfo.linkname,
  1419.             print
  1420.  
  1421.     def add(self, name, arcname=None, recursive=True):
  1422.         """Add the file `name' to the archive. `name' may be any type of file
  1423.            (directory, fifo, symbolic link, etc.). If given, `arcname'
  1424.            specifies an alternative name for the file in the archive.
  1425.            Directories are added recursively by default. This can be avoided by
  1426.            setting `recursive' to False.
  1427.         """
  1428.         self._check("aw")
  1429.  
  1430.         if arcname is None:
  1431.             arcname = name
  1432.  
  1433.         # Skip if somebody tries to archive the archive...
  1434.         if self.name is not None and os.path.abspath(name) == self.name:
  1435.             self._dbg(2, "tarfile: Skipped %r" % name)
  1436.             return
  1437.  
  1438.         # Special case: The user wants to add the current
  1439.         # working directory.
  1440.         if name == ".":
  1441.             if recursive:
  1442.                 if arcname == ".":
  1443.                     arcname = ""
  1444.                 for f in os.listdir("."):
  1445.                     self.add(f, os.path.join(arcname, f))
  1446.             return
  1447.  
  1448.         self._dbg(1, name)
  1449.  
  1450.         # Create a TarInfo object from the file.
  1451.         tarinfo = self.gettarinfo(name, arcname)
  1452.  
  1453.         if tarinfo is None:
  1454.             self._dbg(1, "tarfile: Unsupported type %r" % name)
  1455.             return
  1456.  
  1457.         # Append the tar header and data to the archive.
  1458.         if tarinfo.isreg():
  1459.             f = file(name, "rb")
  1460.             self.addfile(tarinfo, f)
  1461.             f.close()
  1462.  
  1463.         elif tarinfo.isdir():
  1464.             self.addfile(tarinfo)
  1465.             if recursive:
  1466.                 for f in os.listdir(name):
  1467.                     self.add(os.path.join(name, f), os.path.join(arcname, f))
  1468.  
  1469.         else:
  1470.             self.addfile(tarinfo)
  1471.  
  1472.     def addfile(self, tarinfo, fileobj=None):
  1473.         """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
  1474.            given, tarinfo.size bytes are read from it and added to the archive.
  1475.            You can create TarInfo objects using gettarinfo().
  1476.            On Windows platforms, `fileobj' should always be opened with mode
  1477.            'rb' to avoid irritation about the file size.
  1478.         """
  1479.         self._check("aw")
  1480.  
  1481.         tarinfo = copy.copy(tarinfo)
  1482.  
  1483.         buf = tarinfo.tobuf(self.posix)
  1484.         self.fileobj.write(buf)
  1485.         self.offset += len(buf)
  1486.  
  1487.         # If there's data to follow, append it.
  1488.         if fileobj is not None:
  1489.             copyfileobj(fileobj, self.fileobj, tarinfo.size)
  1490.             blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
  1491.             if remainder > 0:
  1492.                 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
  1493.                 blocks += 1
  1494.             self.offset += blocks * BLOCKSIZE
  1495.  
  1496.         self.members.append(tarinfo)
  1497.  
  1498.     def extractall(self, path=".", members=None):
  1499.         """Extract all members from the archive to the current working
  1500.            directory and set owner, modification time and permissions on
  1501.            directories afterwards. `path' specifies a different directory
  1502.            to extract to. `members' is optional and must be a subset of the
  1503.            list returned by getmembers().
  1504.         """
  1505.         directories = []
  1506.  
  1507.         if members is None:
  1508.             members = self
  1509.  
  1510.         for tarinfo in members:
  1511.             if tarinfo.isdir():
  1512.                 # Extract directory with a safe mode, so that
  1513.                 # all files below can be extracted as well.
  1514.                 try:
  1515.                     os.makedirs(os.path.join(path, tarinfo.name), 0777)
  1516.                 except EnvironmentError:
  1517.                     pass
  1518.                 directories.append(tarinfo)
  1519.             else:
  1520.                 self.extract(tarinfo, path)
  1521.  
  1522.         # Reverse sort directories.
  1523.         directories.sort(lambda a, b: cmp(a.name, b.name))
  1524.         directories.reverse()
  1525.  
  1526.         # Set correct owner, mtime and filemode on directories.
  1527.         for tarinfo in directories:
  1528.             path = os.path.join(path, tarinfo.name)
  1529.             try:
  1530.                 self.chown(tarinfo, path)
  1531.                 self.utime(tarinfo, path)
  1532.                 self.chmod(tarinfo, path)
  1533.             except ExtractError, e:
  1534.                 if self.errorlevel > 1:
  1535.                     raise
  1536.                 else:
  1537.                     self._dbg(1, "tarfile: %s" % e)
  1538.  
  1539.     def extract(self, member, path=""):
  1540.         """Extract a member from the archive to the current working directory,
  1541.            using its full name. Its file information is extracted as accurately
  1542.            as possible. `member' may be a filename or a TarInfo object. You can
  1543.            specify a different directory using `path'.
  1544.         """
  1545.         self._check("r")
  1546.  
  1547.         if isinstance(member, TarInfo):
  1548.             tarinfo = member
  1549.         else:
  1550.             tarinfo = self.getmember(member)
  1551.  
  1552.         # Prepare the link target for makelink().
  1553.         if tarinfo.islnk():
  1554.             tarinfo._link_target = os.path.join(path, tarinfo.linkname)
  1555.  
  1556.         try:
  1557.             self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
  1558.         except EnvironmentError, e:
  1559.             if self.errorlevel > 0:
  1560.                 raise
  1561.             else:
  1562.                 if e.filename is None:
  1563.                     self._dbg(1, "tarfile: %s" % e.strerror)
  1564.                 else:
  1565.                     self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
  1566.         except ExtractError, e:
  1567.             if self.errorlevel > 1:
  1568.                 raise
  1569.             else:
  1570.                 self._dbg(1, "tarfile: %s" % e)
  1571.  
  1572.     def extractfile(self, member):
  1573.         """Extract a member from the archive as a file object. `member' may be
  1574.            a filename or a TarInfo object. If `member' is a regular file, a
  1575.            file-like object is returned. If `member' is a link, a file-like
  1576.            object is constructed from the link's target. If `member' is none of
  1577.            the above, None is returned.
  1578.            The file-like object is read-only and provides the following
  1579.            methods: read(), readline(), readlines(), seek() and tell()
  1580.         """
  1581.         self._check("r")
  1582.  
  1583.         if isinstance(member, TarInfo):
  1584.             tarinfo = member
  1585.         else:
  1586.             tarinfo = self.getmember(member)
  1587.  
  1588.         if tarinfo.isreg():
  1589.             return self.fileobject(self, tarinfo)
  1590.  
  1591.         elif tarinfo.type not in SUPPORTED_TYPES:
  1592.             # If a member's type is unknown, it is treated as a
  1593.             # regular file.
  1594.             return self.fileobject(self, tarinfo)
  1595.  
  1596.         elif tarinfo.islnk() or tarinfo.issym():
  1597.             if isinstance(self.fileobj, _Stream):
  1598.                 # A small but ugly workaround for the case that someone tries
  1599.                 # to extract a (sym)link as a file-object from a non-seekable
  1600.                 # stream of tar blocks.
  1601.                 raise StreamError("cannot extract (sym)link as file object")
  1602.             else:
  1603.                 # A (sym)link's file object is its target's file object.
  1604.                 return self.extractfile(self._getmember(tarinfo.linkname,
  1605.                                                         tarinfo))
  1606.         else:
  1607.             # If there's no data associated with the member (directory, chrdev,
  1608.             # blkdev, etc.), return None instead of a file object.
  1609.             return None
  1610.  
  1611.     def _extract_member(self, tarinfo, targetpath):
  1612.         """Extract the TarInfo object tarinfo to a physical
  1613.            file called targetpath.
  1614.         """
  1615.         # Fetch the TarInfo object for the given name
  1616.         # and build the destination pathname, replacing
  1617.         # forward slashes to platform specific separators.
  1618.         if targetpath[-1:] == "/":
  1619.             targetpath = targetpath[:-1]
  1620.         targetpath = os.path.normpath(targetpath)
  1621.  
  1622.         # Create all upper directories.
  1623.         upperdirs = os.path.dirname(targetpath)
  1624.         if upperdirs and not os.path.exists(upperdirs):
  1625.             ti = TarInfo()
  1626.             ti.name  = upperdirs
  1627.             ti.type  = DIRTYPE
  1628.             ti.mode  = 0777
  1629.             ti.mtime = tarinfo.mtime
  1630.             ti.uid   = tarinfo.uid
  1631.             ti.gid   = tarinfo.gid
  1632.             ti.uname = tarinfo.uname
  1633.             ti.gname = tarinfo.gname
  1634.             try:
  1635.                 self._extract_member(ti, ti.name)
  1636.             except:
  1637.                 pass
  1638.  
  1639.         if tarinfo.islnk() or tarinfo.issym():
  1640.             self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
  1641.         else:
  1642.             self._dbg(1, tarinfo.name)
  1643.  
  1644.         if tarinfo.isreg():
  1645.             self.makefile(tarinfo, targetpath)
  1646.         elif tarinfo.isdir():
  1647.             self.makedir(tarinfo, targetpath)
  1648.         elif tarinfo.isfifo():
  1649.             self.makefifo(tarinfo, targetpath)
  1650.         elif tarinfo.ischr() or tarinfo.isblk():
  1651.             self.makedev(tarinfo, targetpath)
  1652.         elif tarinfo.islnk() or tarinfo.issym():
  1653.             self.makelink(tarinfo, targetpath)
  1654.         elif tarinfo.type not in SUPPORTED_TYPES:
  1655.             self.makeunknown(tarinfo, targetpath)
  1656.         else:
  1657.             self.makefile(tarinfo, targetpath)
  1658.  
  1659.         self.chown(tarinfo, targetpath)
  1660.         if not tarinfo.issym():
  1661.             self.chmod(tarinfo, targetpath)
  1662.             self.utime(tarinfo, targetpath)
  1663.  
  1664.     #--------------------------------------------------------------------------
  1665.     # Below are the different file methods. They are called via
  1666.     # _extract_member() when extract() is called. They can be replaced in a
  1667.     # subclass to implement other functionality.
  1668.  
  1669.     def makedir(self, tarinfo, targetpath):
  1670.         """Make a directory called targetpath.
  1671.         """
  1672.         try:
  1673.             os.mkdir(targetpath)
  1674.         except EnvironmentError, e:
  1675.             if e.errno != errno.EEXIST:
  1676.                 raise
  1677.  
  1678.     def makefile(self, tarinfo, targetpath):
  1679.         """Make a file called targetpath.
  1680.         """
  1681.         source = self.extractfile(tarinfo)
  1682.         target = file(targetpath, "wb")
  1683.         copyfileobj(source, target)
  1684.         source.close()
  1685.         target.close()
  1686.  
  1687.     def makeunknown(self, tarinfo, targetpath):
  1688.         """Make a file from a TarInfo object with an unknown type
  1689.            at targetpath.
  1690.         """
  1691.         self.makefile(tarinfo, targetpath)
  1692.         self._dbg(1, "tarfile: Unknown file type %r, " \
  1693.                      "extracted as regular file." % tarinfo.type)
  1694.  
  1695.     def makefifo(self, tarinfo, targetpath):
  1696.         """Make a fifo called targetpath.
  1697.         """
  1698.         if hasattr(os, "mkfifo"):
  1699.             os.mkfifo(targetpath)
  1700.         else:
  1701.             raise ExtractError("fifo not supported by system")
  1702.  
  1703.     def makedev(self, tarinfo, targetpath):
  1704.         """Make a character or block device called targetpath.
  1705.         """
  1706.         if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
  1707.             raise ExtractError("special devices not supported by system")
  1708.  
  1709.         mode = tarinfo.mode
  1710.         if tarinfo.isblk():
  1711.             mode |= stat.S_IFBLK
  1712.         else:
  1713.             mode |= stat.S_IFCHR
  1714.  
  1715.         os.mknod(targetpath, mode,
  1716.                  os.makedev(tarinfo.devmajor, tarinfo.devminor))
  1717.  
  1718.     def makelink(self, tarinfo, targetpath):
  1719.         """Make a (symbolic) link called targetpath. If it cannot be created
  1720.           (platform limitation), we try to make a copy of the referenced file
  1721.           instead of a link.
  1722.         """
  1723.         linkpath = tarinfo.linkname
  1724.         try:
  1725.             if tarinfo.issym():
  1726.                 os.symlink(linkpath, targetpath)
  1727.             else:
  1728.                 # See extract().
  1729.                 os.link(tarinfo._link_target, targetpath)
  1730.         except AttributeError:
  1731.             if tarinfo.issym():
  1732.                 linkpath = os.path.join(os.path.dirname(tarinfo.name),
  1733.                                         linkpath)
  1734.                 linkpath = normpath(linkpath)
  1735.  
  1736.             try:
  1737.                 self._extract_member(self.getmember(linkpath), targetpath)
  1738.             except (EnvironmentError, KeyError), e:
  1739.                 linkpath = os.path.normpath(linkpath)
  1740.                 try:
  1741.                     shutil.copy2(linkpath, targetpath)
  1742.                 except EnvironmentError, e:
  1743.                     raise IOError("link could not be created")
  1744.  
  1745.     def chown(self, tarinfo, targetpath):
  1746.         """Set owner of targetpath according to tarinfo.
  1747.         """
  1748.         if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
  1749.             # We have to be root to do so.
  1750.             try:
  1751.                 g = grp.getgrnam(tarinfo.gname)[2]
  1752.             except KeyError:
  1753.                 try:
  1754.                     g = grp.getgrgid(tarinfo.gid)[2]
  1755.                 except KeyError:
  1756.                     g = os.getgid()
  1757.             try:
  1758.                 u = pwd.getpwnam(tarinfo.uname)[2]
  1759.             except KeyError:
  1760.                 try:
  1761.                     u = pwd.getpwuid(tarinfo.uid)[2]
  1762.                 except KeyError:
  1763.                     u = os.getuid()
  1764.             try:
  1765.                 if tarinfo.issym() and hasattr(os, "lchown"):
  1766.                     os.lchown(targetpath, u, g)
  1767.                 else:
  1768.                     if sys.platform != "os2emx":
  1769.                         os.chown(targetpath, u, g)
  1770.             except EnvironmentError, e:
  1771.                 raise ExtractError("could not change owner")
  1772.  
  1773.     def chmod(self, tarinfo, targetpath):
  1774.         """Set file permissions of targetpath according to tarinfo.
  1775.         """
  1776.         if hasattr(os, 'chmod'):
  1777.             try:
  1778.                 os.chmod(targetpath, tarinfo.mode)
  1779.             except EnvironmentError, e:
  1780.                 raise ExtractError("could not change mode")
  1781.  
  1782.     def utime(self, tarinfo, targetpath):
  1783.         """Set modification time of targetpath according to tarinfo.
  1784.         """
  1785.         if not hasattr(os, 'utime'):
  1786.             return
  1787.         if sys.platform == "win32" and tarinfo.isdir():
  1788.             # According to msdn.microsoft.com, it is an error (EACCES)
  1789.             # to use utime() on directories.
  1790.             return
  1791.         try:
  1792.             os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
  1793.         except EnvironmentError, e:
  1794.             raise ExtractError("could not change modification time")
  1795.  
  1796.     #--------------------------------------------------------------------------
  1797.     def next(self):
  1798.         """Return the next member of the archive as a TarInfo object, when
  1799.            TarFile is opened for reading. Return None if there is no more
  1800.            available.
  1801.         """
  1802.         self._check("ra")
  1803.         if self.firstmember is not None:
  1804.             m = self.firstmember
  1805.             self.firstmember = None
  1806.             return m
  1807.  
  1808.         # Read the next block.
  1809.         self.fileobj.seek(self.offset)
  1810.         while True:
  1811.             buf = self.fileobj.read(BLOCKSIZE)
  1812.             if not buf:
  1813.                 return None
  1814.  
  1815.             try:
  1816.                 tarinfo = TarInfo.frombuf(buf)
  1817.  
  1818.                 # Set the TarInfo object's offset to the current position of the
  1819.                 # TarFile and set self.offset to the position where the data blocks
  1820.                 # should begin.
  1821.                 tarinfo.offset = self.offset
  1822.                 self.offset += BLOCKSIZE
  1823.  
  1824.                 tarinfo = self.proc_member(tarinfo)
  1825.  
  1826.             except ValueError, e:
  1827.                 if self.ignore_zeros:
  1828.                     self._dbg(2, "0x%X: empty or invalid block: %s" %
  1829.                               (self.offset, e))
  1830.                     self.offset += BLOCKSIZE
  1831.                     continue
  1832.                 else:
  1833.                     if self.offset == 0:
  1834.                         raise ReadError("empty, unreadable or compressed "
  1835.                                         "file: %s" % e)
  1836.                     return None
  1837.             break
  1838.  
  1839.         # Some old tar programs represent a directory as a regular
  1840.         # file with a trailing slash.
  1841.         if tarinfo.isreg() and tarinfo.name.endswith("/"):
  1842.             tarinfo.type = DIRTYPE
  1843.  
  1844.         # Directory names should have a '/' at the end.
  1845.         if tarinfo.isdir():
  1846.             tarinfo.name += "/"
  1847.  
  1848.         self.members.append(tarinfo)
  1849.         return tarinfo
  1850.  
  1851.     #--------------------------------------------------------------------------
  1852.     # The following are methods that are called depending on the type of a
  1853.     # member. The entry point is proc_member() which is called with a TarInfo
  1854.     # object created from the header block from the current offset. The
  1855.     # proc_member() method can be overridden in a subclass to add custom
  1856.     # proc_*() methods. A proc_*() method MUST implement the following
  1857.     # operations:
  1858.     # 1. Set tarinfo.offset_data to the position where the data blocks begin,
  1859.     #    if there is data that follows.
  1860.     # 2. Set self.offset to the position where the next member's header will
  1861.     #    begin.
  1862.     # 3. Return tarinfo or another valid TarInfo object.
  1863.     def proc_member(self, tarinfo):
  1864.         """Choose the right processing method for tarinfo depending
  1865.            on its type and call it.
  1866.         """
  1867.         if tarinfo.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  1868.             return self.proc_gnulong(tarinfo)
  1869.         elif tarinfo.type == GNUTYPE_SPARSE:
  1870.             return self.proc_sparse(tarinfo)
  1871.         else:
  1872.             return self.proc_builtin(tarinfo)
  1873.  
  1874.     def proc_builtin(self, tarinfo):
  1875.         """Process a builtin type member or an unknown member
  1876.            which will be treated as a regular file.
  1877.         """
  1878.         tarinfo.offset_data = self.offset
  1879.         if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES:
  1880.             # Skip the following data blocks.
  1881.             self.offset += self._block(tarinfo.size)
  1882.         return tarinfo
  1883.  
  1884.     def proc_gnulong(self, tarinfo):
  1885.         """Process the blocks that hold a GNU longname
  1886.            or longlink member.
  1887.         """
  1888.         buf = ""
  1889.         count = tarinfo.size
  1890.         while count > 0:
  1891.             block = self.fileobj.read(BLOCKSIZE)
  1892.             buf += block
  1893.             self.offset += BLOCKSIZE
  1894.             count -= BLOCKSIZE
  1895.  
  1896.         # Fetch the next header and process it.
  1897.         b = self.fileobj.read(BLOCKSIZE)
  1898.         t = TarInfo.frombuf(b)
  1899.         t.offset = self.offset
  1900.         self.offset += BLOCKSIZE
  1901.         next = self.proc_member(t)
  1902.  
  1903.         # Patch the TarInfo object from the next header with
  1904.         # the longname information.
  1905.         next.offset = tarinfo.offset
  1906.         if tarinfo.type == GNUTYPE_LONGNAME:
  1907.             next.name = buf.rstrip(NUL)
  1908.         elif tarinfo.type == GNUTYPE_LONGLINK:
  1909.             next.linkname = buf.rstrip(NUL)
  1910.  
  1911.         return next
  1912.  
  1913.     def proc_sparse(self, tarinfo):
  1914.         """Process a GNU sparse header plus extra headers.
  1915.         """
  1916.         buf = tarinfo.buf
  1917.         sp = _ringbuffer()
  1918.         pos = 386
  1919.         lastpos = 0L
  1920.         realpos = 0L
  1921.         # There are 4 possible sparse structs in the
  1922.         # first header.
  1923.         for i in xrange(4):
  1924.             try:
  1925.                 offset = nti(buf[pos:pos + 12])
  1926.                 numbytes = nti(buf[pos + 12:pos + 24])
  1927.             except ValueError:
  1928.                 break
  1929.             if offset > lastpos:
  1930.                 sp.append(_hole(lastpos, offset - lastpos))
  1931.             sp.append(_data(offset, numbytes, realpos))
  1932.             realpos += numbytes
  1933.             lastpos = offset + numbytes
  1934.             pos += 24
  1935.  
  1936.         isextended = ord(buf[482])
  1937.         origsize = nti(buf[483:495])
  1938.  
  1939.         # If the isextended flag is given,
  1940.         # there are extra headers to process.
  1941.         while isextended == 1:
  1942.             buf = self.fileobj.read(BLOCKSIZE)
  1943.             self.offset += BLOCKSIZE
  1944.             pos = 0
  1945.             for i in xrange(21):
  1946.                 try:
  1947.                     offset = nti(buf[pos:pos + 12])
  1948.                     numbytes = nti(buf[pos + 12:pos + 24])
  1949.                 except ValueError:
  1950.                     break
  1951.                 if offset > lastpos:
  1952.                     sp.append(_hole(lastpos, offset - lastpos))
  1953.                 sp.append(_data(offset, numbytes, realpos))
  1954.                 realpos += numbytes
  1955.                 lastpos = offset + numbytes
  1956.                 pos += 24
  1957.             isextended = ord(buf[504])
  1958.  
  1959.         if lastpos < origsize:
  1960.             sp.append(_hole(lastpos, origsize - lastpos))
  1961.  
  1962.         tarinfo.sparse = sp
  1963.  
  1964.         tarinfo.offset_data = self.offset
  1965.         self.offset += self._block(tarinfo.size)
  1966.         tarinfo.size = origsize
  1967.  
  1968.         return tarinfo
  1969.  
  1970.     #--------------------------------------------------------------------------
  1971.     # Little helper methods:
  1972.  
  1973.     def _block(self, count):
  1974.         """Round up a byte count by BLOCKSIZE and return it,
  1975.            e.g. _block(834) => 1024.
  1976.         """
  1977.         blocks, remainder = divmod(count, BLOCKSIZE)
  1978.         if remainder:
  1979.             blocks += 1
  1980.         return blocks * BLOCKSIZE
  1981.  
  1982.     def _getmember(self, name, tarinfo=None):
  1983.         """Find an archive member by name from bottom to top.
  1984.            If tarinfo is given, it is used as the starting point.
  1985.         """
  1986.         # Ensure that all members have been loaded.
  1987.         members = self.getmembers()
  1988.  
  1989.         if tarinfo is None:
  1990.             end = len(members)
  1991.         else:
  1992.             end = members.index(tarinfo)
  1993.  
  1994.         for i in xrange(end - 1, -1, -1):
  1995.             if name == members[i].name:
  1996.                 return members[i]
  1997.  
  1998.     def _load(self):
  1999.         """Read through the entire archive file and look for readable
  2000.            members.
  2001.         """
  2002.         while True:
  2003.             tarinfo = self.next()
  2004.             if tarinfo is None:
  2005.                 break
  2006.         self._loaded = True
  2007.  
  2008.     def _check(self, mode=None):
  2009.         """Check if TarFile is still open, and if the operation's mode
  2010.            corresponds to TarFile's mode.
  2011.         """
  2012.         if self.closed:
  2013.             raise IOError("%s is closed" % self.__class__.__name__)
  2014.         if mode is not None and self._mode not in mode:
  2015.             raise IOError("bad operation for mode %r" % self._mode)
  2016.  
  2017.     def __iter__(self):
  2018.         """Provide an iterator object.
  2019.         """
  2020.         if self._loaded:
  2021.             return iter(self.members)
  2022.         else:
  2023.             return TarIter(self)
  2024.  
  2025.     def _dbg(self, level, msg):
  2026.         """Write debugging output to sys.stderr.
  2027.         """
  2028.         if level <= self.debug:
  2029.             print >> sys.stderr, msg
  2030. # class TarFile
  2031.  
  2032. class TarIter:
  2033.     """Iterator Class.
  2034.  
  2035.        for tarinfo in TarFile(...):
  2036.            suite...
  2037.     """
  2038.  
  2039.     def __init__(self, tarfile):
  2040.         """Construct a TarIter object.
  2041.         """
  2042.         self.tarfile = tarfile
  2043.         self.index = 0
  2044.     def __iter__(self):
  2045.         """Return iterator object.
  2046.         """
  2047.         return self
  2048.     def next(self):
  2049.         """Return the next item using TarFile's next() method.
  2050.            When all members have been read, set TarFile as _loaded.
  2051.         """
  2052.         # Fix for SF #1100429: Under rare circumstances it can
  2053.         # happen that getmembers() is called during iteration,
  2054.         # which will cause TarIter to stop prematurely.
  2055.         if not self.tarfile._loaded:
  2056.             tarinfo = self.tarfile.next()
  2057.             if not tarinfo:
  2058.                 self.tarfile._loaded = True
  2059.                 raise StopIteration
  2060.         else:
  2061.             try:
  2062.                 tarinfo = self.tarfile.members[self.index]
  2063.             except IndexError:
  2064.                 raise StopIteration
  2065.         self.index += 1
  2066.         return tarinfo
  2067.  
  2068. # Helper classes for sparse file support
  2069. class _section:
  2070.     """Base class for _data and _hole.
  2071.     """
  2072.     def __init__(self, offset, size):
  2073.         self.offset = offset
  2074.         self.size = size
  2075.     def __contains__(self, offset):
  2076.         return self.offset <= offset < self.offset + self.size
  2077.  
  2078. class _data(_section):
  2079.     """Represent a data section in a sparse file.
  2080.     """
  2081.     def __init__(self, offset, size, realpos):
  2082.         _section.__init__(self, offset, size)
  2083.         self.realpos = realpos
  2084.  
  2085. class _hole(_section):
  2086.     """Represent a hole section in a sparse file.
  2087.     """
  2088.     pass
  2089.  
  2090. class _ringbuffer(list):
  2091.     """Ringbuffer class which increases performance
  2092.        over a regular list.
  2093.     """
  2094.     def __init__(self):
  2095.         self.idx = 0
  2096.     def find(self, offset):
  2097.         idx = self.idx
  2098.         while True:
  2099.             item = self[idx]
  2100.             if offset in item:
  2101.                 break
  2102.             idx += 1
  2103.             if idx == len(self):
  2104.                 idx = 0
  2105.             if idx == self.idx:
  2106.                 # End of File
  2107.                 return None
  2108.         self.idx = idx
  2109.         return item
  2110.  
  2111. #---------------------------------------------
  2112. # zipfile compatible TarFile class
  2113. #---------------------------------------------
  2114. TAR_PLAIN = 0           # zipfile.ZIP_STORED
  2115. TAR_GZIPPED = 8         # zipfile.ZIP_DEFLATED
  2116. class TarFileCompat:
  2117.     """TarFile class compatible with standard module zipfile's
  2118.        ZipFile class.
  2119.     """
  2120.     def __init__(self, file, mode="r", compression=TAR_PLAIN):
  2121.         if compression == TAR_PLAIN:
  2122.             self.tarfile = TarFile.taropen(file, mode)
  2123.         elif compression == TAR_GZIPPED:
  2124.             self.tarfile = TarFile.gzopen(file, mode)
  2125.         else:
  2126.             raise ValueError("unknown compression constant")
  2127.         if mode[0:1] == "r":
  2128.             members = self.tarfile.getmembers()
  2129.             for m in members:
  2130.                 m.filename = m.name
  2131.                 m.file_size = m.size
  2132.                 m.date_time = time.gmtime(m.mtime)[:6]
  2133.     def namelist(self):
  2134.         return map(lambda m: m.name, self.infolist())
  2135.     def infolist(self):
  2136.         return filter(lambda m: m.type in REGULAR_TYPES,
  2137.                       self.tarfile.getmembers())
  2138.     def printdir(self):
  2139.         self.tarfile.list()
  2140.     def testzip(self):
  2141.         return
  2142.     def getinfo(self, name):
  2143.         return self.tarfile.getmember(name)
  2144.     def read(self, name):
  2145.         return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
  2146.     def write(self, filename, arcname=None, compress_type=None):
  2147.         self.tarfile.add(filename, arcname)
  2148.     def writestr(self, zinfo, bytes):
  2149.         try:
  2150.             from cStringIO import StringIO
  2151.         except ImportError:
  2152.             from StringIO import StringIO
  2153.         import calendar
  2154.         zinfo.name = zinfo.filename
  2155.         zinfo.size = zinfo.file_size
  2156.         zinfo.mtime = calendar.timegm(zinfo.date_time)
  2157.         self.tarfile.addfile(zinfo, StringIO(bytes))
  2158.     def close(self):
  2159.         self.tarfile.close()
  2160. #class TarFileCompat
  2161.  
  2162. #--------------------
  2163. # exported functions
  2164. #--------------------
  2165. def is_tarfile(name):
  2166.     """Return True if name points to a tar archive that we
  2167.        are able to handle, else return False.
  2168.     """
  2169.     try:
  2170.         t = open(name)
  2171.         t.close()
  2172.         return True
  2173.     except TarError:
  2174.         return False
  2175.  
  2176. open = TarFile.open
  2177.